package org.scep.servlet;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.scep.model.ServerManager;
import org.scep.utils.Utils;


public class ServerServlet extends HttpServlet implements PropertyChangeListener
{
	public static final String CLOSE_PRO = "close_pro";
	public static final String SAVE_PATH = "/file";
	public static final long TIME_OUT = 3000;
	private static final String PARAM = "param";
	private static final String CLOSE = "close";
	private static final String DATA = "data";
	private static final String LIST = "list";
	private static final String DELETE = "delete";
	protected Map query = new HashMap();

	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
//		System.out.println(Utils.getRequestContent(request));
		String type = request.getParameter("type");
		if(PARAM.equals(type)){//文件上传初始信息
			try{
				String name = Utils.toUTF8String(request.getParameter("name"));
//				String name = Utils.getRequestContentToString(request);
				String thread = request.getParameter("thread");
				String point = request.getParameter("point");
				
				int threadNum = Integer.parseInt(thread);
				String []points = point.split("\\|");
				if(threadNum == points.length){
					long []p = new long[threadNum];
					for(int i=0;i<points.length;i++)
						p[i] = new Long(points[i]).longValue();
					
					receiveParam(name,threadNum,p,request.getRealPath(SAVE_PATH));
					doResponse(response,"ok");
					return;
				}
			}catch(Exception e){
				System.err.println(e);
				
			}
		}else if(DATA.equals(type)){//文件数据
			String name = Utils.toUTF8String(request.getParameter("name"));
			String id = request.getParameter("id");
			String length = request.getParameter("length");
			String timestamp = request.getParameter("timestamp");
			byte[] b = Utils.getRequestContentToBytes(request);
			receive(name,new Integer(id).intValue(), b,new Integer(length).intValue(),timestamp);
			doResponse(response,"ok");
			return;
		}else if(CLOSE.equals(type)){//关闭上传
			String name = Utils.toUTF8String(request.getParameter("name"));
			close(name);
			doResponse(response,"ok");
			return;
		}else if(LIST.equals(type)){//文件列表
			File file = new File(request.getRealPath(SAVE_PATH));
			if(file.exists()){
				File []lf = file.listFiles();
				StringBuffer sb = new StringBuffer();
				for(int i=0,len=lf.length;i<len;i++){
					if(i == 0)
						sb.append(lf[i].getName());
					else
						sb.append("|" + lf[i].getName());
				}
				doResponse(response,URLEncoder.encode(sb.toString(), "UTF-8"));
			}
		}else if(DELETE.equals(type)){//删除文件
			String name = Utils.toUTF8String(request.getParameter("name"));
			File file = new File(request.getRealPath(SAVE_PATH + File.separator + name));
			if(file.exists()){
				file.delete();
			}
			doResponse(response,"ok");
		}
		
		doResponse(response,"error");
	}

	/**
	 * 模拟服务端调用
	 */
	public boolean receiveParam(String name, int threadNum, long[] startPos,String savepath)
	{
		if(name == null || name.trim().equals(""))
			return false;
		
		if(query.get(name) != null)
			return true;
		
		try{
			ServerManager ulm = new ServerManager(savepath,name,threadNum,startPos);
			query.put(name, ulm);
			ulm.addPropertyChangeListener(this);
		}catch(Exception e){
			System.err.println(e);
			return false;
		}
		
		return true;
	}
	
	public boolean receive(String name,int id, byte[] b,int length,String timestamp){
		
		if(!query.containsKey(name))
			return false;
		
		ServerManager ulm = (ServerManager)query.get(name);
		if(ulm == null){
			query.remove(name);
			return false;
		}
		
		try{
			return ulm.write(id,b,length,timestamp);
		}catch(Exception e){
			System.err.println(e);
			return false;
		}
	}

	public boolean close(String name)
	{
		ServerManager ulm = (ServerManager)query.get(name);
		if(ulm != null){
			ulm.close();
			query.remove(name);
			System.out.println("the upload connection [" + name +"] is close.");
		}
		
		return true;
	}
	
	public void doResponse(HttpServletResponse response,String info) throws IOException{
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print(info);
		out.flush();
		out.close();
	}
	
	
	public void propertyChange(PropertyChangeEvent evt) {
		if(CLOSE_PRO.equals(evt.getPropertyName())){
			String name = (String)evt.getNewValue();
			close(name);
		}
	}

}
